package com.virtualperson.controller;

import com.virtualperson.service.ObjectStorageService;
import com.virtualperson.util.ServerConnectionUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@Slf4j
@Controller
@RequestMapping("/api/upload")
@RequiredArgsConstructor
@Tag(name = "文件上传服务", description = "提供图片和音频文件上传到远程服务器的REST API接口")
public class FileUploadController {

    private final ObjectStorageService objectStorageService;
    private final ServerConnectionUtil serverConnectionUtil;

    @GetMapping("/page")
    @Operation(
        summary = "文件上传页面",
        description = "返回文件上传的前端页面"
    )
    public String uploadPage() {
        return "file-upload";
    }

    @PostMapping("/image")
    @Operation(
        summary = "上传图片文件",
        description = "将本地图片文件上传到远程服务器并返回访问URL"
    )
    @ApiResponses(value = {
        @ApiResponse(
            responseCode = "200",
            description = "上传成功",
            content = @Content(schema = @Schema(implementation = UploadResponse.class))
        ),
        @ApiResponse(
            responseCode = "400",
            description = "文件格式不支持或文件过大",
            content = @Content(schema = @Schema(implementation = ErrorResponse.class))
        ),
        @ApiResponse(
            responseCode = "500",
            description = "服务器内部错误",
            content = @Content(schema = @Schema(implementation = ErrorResponse.class))
        )
    })
    public ResponseEntity<?> uploadImage(
        @Parameter(description = "图片文件", required = true)
        @RequestParam("file") MultipartFile file
    ) {
        log.info("收到图片上传请求: 文件名={}, 大小={}字节", file.getOriginalFilename(), file.getSize());
        
        try {
            // 验证文件
            validateImageFile(file);
            
            // 保存到临时文件
            File tempFile = saveToTempFile(file, "image");
            
            // 上传到远程服务器
            String remoteUrl = objectStorageService.uploadFile(tempFile);
            
            // 清理临时文件
            tempFile.delete();
            
            log.info("图片上传成功: {}", remoteUrl);
            return ResponseEntity.ok(new UploadResponse("SUCCESS", remoteUrl, file.getOriginalFilename()));
            
        } catch (Exception e) {
            log.error("图片上传失败", e);
            return ResponseEntity.badRequest()
                .body(new ErrorResponse("ERROR", "图片上传失败: " + e.getMessage()));
        }
    }

    @PostMapping("/audio")
    @Operation(
        summary = "上传音频文件",
        description = "将本地音频文件上传到远程服务器并返回访问URL"
    )
    @ApiResponses(value = {
        @ApiResponse(
            responseCode = "200",
            description = "上传成功",
            content = @Content(schema = @Schema(implementation = UploadResponse.class))
        ),
        @ApiResponse(
            responseCode = "400",
            description = "文件格式不支持或文件过大",
            content = @Content(schema = @Schema(implementation = ErrorResponse.class))
        ),
        @ApiResponse(
            responseCode = "500",
            description = "服务器内部错误",
            content = @Content(schema = @Schema(implementation = ErrorResponse.class))
        )
    })
    public ResponseEntity<?> uploadAudio(
        @Parameter(description = "音频文件", required = true)
        @RequestParam("file") MultipartFile file
    ) {
        log.info("收到音频上传请求: 文件名={}, 大小={}字节", file.getOriginalFilename(), file.getSize());
        
        try {
            // 验证文件
            validateAudioFile(file);
            
            // 保存到临时文件
            File tempFile = saveToTempFile(file, "audio");
            
            // 上传到远程服务器
            String remoteUrl = objectStorageService.uploadFile(tempFile);
            
            // 清理临时文件
            tempFile.delete();
            
            log.info("音频上传成功: {}", remoteUrl);
            return ResponseEntity.ok(new UploadResponse("SUCCESS", remoteUrl, file.getOriginalFilename()));
            
        } catch (Exception e) {
            log.error("音频上传失败", e);
            return ResponseEntity.badRequest()
                .body(new ErrorResponse("ERROR", "音频上传失败: " + e.getMessage()));
        }
    }

    @PostMapping("/file")
    @Operation(
        summary = "上传任意文件",
        description = "将任意文件上传到远程服务器并返回访问URL"
    )
    public ResponseEntity<?> uploadFile(
        @Parameter(description = "文件", required = true)
        @RequestParam("file") MultipartFile file
    ) {
        log.info("收到文件上传请求: 文件名={}, 大小={}字节", file.getOriginalFilename(), file.getSize());
        
        try {
            // 验证文件大小
            if (file.getSize() > 50 * 1024 * 1024) { // 50MB限制
                throw new IllegalArgumentException("文件大小不能超过50MB");
            }
            
            // 保存到临时文件
            File tempFile = saveToTempFile(file, "file");
            
            // 上传到远程服务器
            String remoteUrl = objectStorageService.uploadFile(tempFile);
            
            // 清理临时文件
            tempFile.delete();
            
            log.info("文件上传成功: {}", remoteUrl);
            return ResponseEntity.ok(new UploadResponse("SUCCESS", remoteUrl, file.getOriginalFilename()));
            
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return ResponseEntity.badRequest()
                .body(new ErrorResponse("ERROR", "文件上传失败: " + e.getMessage()));
        }
    }

    @GetMapping("/test-connection")
    @Operation(
        summary = "测试服务器连接",
        description = "测试与远程服务器的SSH/SFTP连接"
    )
    public ResponseEntity<?> testServerConnection() {
        try {
            ServerConnectionUtil.ConnectionTestResult result = serverConnectionUtil.testConnection();
            
            if (result.isSuccess()) {
                return ResponseEntity.ok(new TestConnectionResponse("SUCCESS", result.getMessage()));
            } else {
                return ResponseEntity.badRequest()
                    .body(new TestConnectionResponse("ERROR", result.getMessage()));
            }
        } catch (Exception e) {
            log.error("测试服务器连接失败", e);
            return ResponseEntity.internalServerError()
                .body(new TestConnectionResponse("ERROR", "测试连接失败: " + e.getMessage()));
        }
    }

    @GetMapping("/check-directory")
    @Operation(
        summary = "检查远程目录",
        description = "检查远程服务器上的存储目录是否存在"
    )
    public ResponseEntity<?> checkRemoteDirectory() {
        try {
            // 从配置中获取远程路径
            String remotePath = "/var/www/uploads"; // 这里可以从配置中读取
            
            ServerConnectionUtil.DirectoryCheckResult result = serverConnectionUtil.checkRemoteDirectory(remotePath);
            
            if (result.isConnectionSuccess()) {
                return ResponseEntity.ok(new DirectoryCheckResponse(
                    "SUCCESS", 
                    result.getMessage(), 
                    result.isDirectoryExists()
                ));
            } else {
                return ResponseEntity.badRequest()
                    .body(new DirectoryCheckResponse("ERROR", result.getMessage(), false));
            }
        } catch (Exception e) {
            log.error("检查远程目录失败", e);
            return ResponseEntity.internalServerError()
                .body(new DirectoryCheckResponse("ERROR", "检查目录失败: " + e.getMessage(), false));
        }
    }

    private void validateImageFile(MultipartFile file) {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("文件不能为空");
        }
        
        if (file.getSize() > 10 * 1024 * 1024) { // 10MB限制
            throw new IllegalArgumentException("图片文件大小不能超过10MB");
        }
        
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || originalFilename.trim().isEmpty()) {
            throw new IllegalArgumentException("文件名不能为空");
        }
        
        String extension = getFileExtension(originalFilename).toLowerCase();
        if (!extension.matches("(jpg|jpeg|png|bmp|webp)")) {
            throw new IllegalArgumentException("图片格式不支持，支持格式：jpg, jpeg, png, bmp, webp");
        }
    }

    private void validateAudioFile(MultipartFile file) {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("文件不能为空");
        }
        
        if (file.getSize() > 15 * 1024 * 1024) { // 15MB限制
            throw new IllegalArgumentException("音频文件大小不能超过15MB");
        }
        
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || originalFilename.trim().isEmpty()) {
            throw new IllegalArgumentException("文件名不能为空");
        }
        
        String extension = getFileExtension(originalFilename).toLowerCase();
        if (!extension.matches("(mp3|wav|ogg|aac)")) {
            throw new IllegalArgumentException("音频格式不支持，支持格式：mp3, wav, ogg, aac");
        }
    }

    private String getFileExtension(String filename) {
        if (filename.contains(".")) {
            return filename.substring(filename.lastIndexOf('.') + 1);
        }
        return "";
    }

    private File saveToTempFile(MultipartFile file, String type) throws IOException {
        // 创建临时目录
        String tempDir = "temp_uploads";
        Path tempPath = Paths.get(tempDir);
        if (!Files.exists(tempPath)) {
            Files.createDirectories(tempPath);
        }
        
        // 生成临时文件名
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        String uuid = UUID.randomUUID().toString().substring(0, 8);
        String extension = getFileExtension(file.getOriginalFilename());
        String tempFileName = String.format("%s_%s_%s.%s", type, timestamp, uuid, extension);
        
        // 保存文件
        Path filePath = tempPath.resolve(tempFileName);
        Files.copy(file.getInputStream(), filePath);
        
        return filePath.toFile();
    }

    // 响应类
    public static class UploadResponse {
        private String status;
        private String url;
        private String filename;

        public UploadResponse(String status, String url, String filename) {
            this.status = status;
            this.url = url;
            this.filename = filename;
        }

        // Getters and Setters
        public String getStatus() { return status; }
        public void setStatus(String status) { this.status = status; }
        public String getUrl() { return url; }
        public void setUrl(String url) { this.url = url; }
        public String getFilename() { return filename; }
        public void setFilename(String filename) { this.filename = filename; }
    }

    public static class ErrorResponse {
        private String status;
        private String message;

        public ErrorResponse(String status, String message) {
            this.status = status;
            this.message = message;
        }

        // Getters and Setters
        public String getStatus() { return status; }
        public void setStatus(String status) { this.status = status; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
    }

    public static class TestConnectionResponse {
        private String status;
        private String message;

        public TestConnectionResponse(String status, String message) {
            this.status = status;
            this.message = message;
        }

        // Getters and Setters
        public String getStatus() { return status; }
        public void setStatus(String status) { this.status = status; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
    }

    public static class DirectoryCheckResponse {
        private String status;
        private String message;
        private boolean directoryExists;

        public DirectoryCheckResponse(String status, String message, boolean directoryExists) {
            this.status = status;
            this.message = message;
            this.directoryExists = directoryExists;
        }

        // Getters and Setters
        public String getStatus() { return status; }
        public void setStatus(String status) { this.status = status; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        public boolean isDirectoryExists() { return directoryExists; }
        public void setDirectoryExists(boolean directoryExists) { this.directoryExists = directoryExists; }
    }
} 